﻿using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media;
namespace Omnia.UX
{
    [ContentProperty("AppBarButtons")]
    public class AppBar : Control, IApplicationBar
    {
        #region - property -
        ApplicationBar _appBar;
        public ApplicationBar ApplicationBar
        {
            get
            {
                if (_appBar == null)
                {
                    _appBar = new ApplicationBar();
                    _appBar.StateChanged += appBar_StateChanged;
                }
                return _appBar;
            }
        }

        PhoneApplicationPage _page;
        public PhoneApplicationPage ParentPage
        {
            get
            { 
                return _page;
            }
            set
            {
                _page = value;
            }
        }
        #endregion

        #region - BackgroundColor -
        public static readonly DependencyProperty BackgroundColorProperty =
        DependencyProperty.Register("BackgroundColor",
        typeof(Color),
        typeof(AppBar),
        new PropertyMetadata(Color.FromArgb(255, 0, 0, 0), new PropertyChangedCallback(AppBar.OnBackgroundColorPropertyChanged)));

        public Color BackgroundColor
        {
            get
            {
                return (Color)base.GetValue(BackgroundColorProperty);
            }
            set
            {
                base.SetValue(BackgroundColorProperty, value);
            }
        }

        private static void OnBackgroundColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.BackgroundColor = (Color)e.NewValue;
        }
        #endregion

        #region - Buttons -
        public IList Buttons
        {
            get;
            set;
        }

        public static readonly DependencyProperty AppBarButtonsProperty =
        DependencyProperty.Register("AppBarButtons",
        typeof(ObservableCollection<AppBarIconButton>),
        typeof(AppBar),
        new PropertyMetadata(null, new PropertyChangedCallback(AppBar.OnAppBarButtonsPropertyChanged)));

        public ObservableCollection<AppBarIconButton> AppBarButtons
        {
            get
            {
                if (base.GetValue(AppBarButtonsProperty) == null)
                    base.SetValue(AppBarButtonsProperty, new ObservableCollection<AppBarIconButton>());
                return base.GetValue(AppBarButtonsProperty) as ObservableCollection<AppBarIconButton>;
            }
            set
            {
                base.SetValue(AppBarButtonsProperty, value);
            }
        }

        private static void OnAppBarButtonsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).AppBarButtonsPropertyChanged(e);
        }

        private void AppBarButtonsPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            var oldButton = e.OldValue as ObservableCollection<AppBarIconButton>;
            if (oldButton != null)
            {
                oldButton.CollectionChanged -= Button_CollectionChanged;
            }

            ApplicationBar.Buttons.Clear();
            var newButton = e.NewValue as ObservableCollection<AppBarIconButton>;
            if (newButton != null)
            {
                foreach (AppBarIconButton item in newButton)
                {
                    ApplicationBar.Buttons.Add(item.ApplicationBarItem);
                }
                newButton.CollectionChanged += Button_CollectionChanged;
            }
        }

        void Button_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        if (e.NewItems != null)
                        {
                            int start = e.NewStartingIndex;
                            foreach (var item in e.NewItems)
                            {
                                AppBarIconButton buttonItem = item as AppBarIconButton;
                                if (buttonItem != null)
                                {
                                    ApplicationBar.Buttons.Insert(start, buttonItem.ApplicationBarItem);
                                }
                                start++;
                            }
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    {
                        if (e.NewItems != null)
                        {
                            foreach (var item in e.NewItems)
                            {
                                AppBarIconButton buttonItem = item as AppBarIconButton;
                                if (buttonItem != null)
                                    ApplicationBar.Buttons.Remove(buttonItem.ApplicationBarItem);
                            }
                        }
                    }
                    break;

                default:
                    {
                        ApplicationBar.Buttons.Clear();
                        if (AppBarButtons != null)
                        {
                            foreach (AppBarIconButton item in AppBarButtons)
                            {
                                ApplicationBar.Buttons.Add(item.ApplicationBarItem);
                            }
                        }
                    }
                    break;
            }
        }
        #endregion

        #region - ForegroundColor -
        public static readonly DependencyProperty ForegroundColorProperty =
        DependencyProperty.Register("ForegroundColor",
        typeof(Color),
        typeof(AppBar),
        new PropertyMetadata(Color.FromArgb(255, 0, 0, 0), new PropertyChangedCallback(AppBar.OnForegroundColorPropertyChanged)));

        public Color ForegroundColor
        {
            get
            {
                return (Color)base.GetValue(ForegroundColorProperty);
            }
            set
            {
                base.SetValue(ForegroundColorProperty, value);
            }
        }

        private static void OnForegroundColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.ForegroundColor = (Color)e.NewValue;
        }
        #endregion

        #region - IsMenuEnabled -
        public static readonly DependencyProperty IsMenuEnabledProperty =
        DependencyProperty.Register("IsMenuEnabled",
        typeof(bool),
        typeof(AppBar),
        new PropertyMetadata(false, new PropertyChangedCallback(AppBar.OnIsMenuEnabledPropertyChanged)));

        public bool IsMenuEnabled
        {
            get
            {
                return (bool)base.GetValue(IsMenuEnabledProperty);
            }
            set
            {
                base.SetValue(IsMenuEnabledProperty, value);
            }
        }

        private static void OnIsMenuEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.IsMenuEnabled = (bool)e.NewValue;
        }
        #endregion

        #region - IsVisible -
        public static readonly DependencyProperty IsVisibleProperty =
            DependencyProperty.Register("IsVisible",
        typeof(bool),
        typeof(AppBar),
        new PropertyMetadata(false, new PropertyChangedCallback(AppBar.OnIsVisiblePropertyChanged)));

        public bool IsVisible
        {
            get
            {
                return (bool)base.GetValue(IsVisibleProperty);
            }
            set
            {
                base.SetValue(IsVisibleProperty, value);
            }
        }

        private static void OnIsVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.IsVisible = (bool)e.NewValue;
        }


        #endregion

        #region - MenuItems -
        public IList MenuItems
        {
            get;
            set;
        }

        public static readonly DependencyProperty MenusProperty =
        DependencyProperty.Register("Menus",
        typeof(ObservableCollection<AppBarMenuItem>),
        typeof(AppBar),
        new PropertyMetadata(null , new PropertyChangedCallback(AppBar.OnMenusPropertyChanged)));

        public ObservableCollection<AppBarMenuItem> Menus
        {
            get
            {
                if (base.GetValue(MenusProperty)==null)
                    base.SetValue(MenusProperty, new ObservableCollection<AppBarMenuItem>());
                return base.GetValue(MenusProperty) as ObservableCollection<AppBarMenuItem>;
            }
            set
            {
                base.SetValue(MenusProperty, value);
            }
        }

        private static void OnMenusPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).MenusPropertyChanged(e);
        }

        private void MenusPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            var oldMenu = e.OldValue as ObservableCollection<AppBarMenuItem>;
            if (oldMenu != null)
            {
                oldMenu.CollectionChanged -= Menu_CollectionChanged;
            }

            ApplicationBar.MenuItems.Clear();
            var newMenu = e.NewValue as ObservableCollection<AppBarMenuItem>;
            if (newMenu != null)
            {
                foreach (AppBarMenuItem item in newMenu)
                {
                    if (!string.IsNullOrEmpty(item.Text))
                    ApplicationBar.MenuItems.Add(item.ApplicationBarItem);
                }
                newMenu.CollectionChanged += Menu_CollectionChanged;
            }
        }

        void Menu_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    {
                        if (e.NewItems != null)
                        {
                            int start = e.NewStartingIndex;
                            foreach (var item in e.NewItems)
                            {
                                AppBarMenuItem menuItem=item as AppBarMenuItem;
                                if (menuItem != null)
                                {
                                    ApplicationBar.MenuItems.Insert(start, menuItem.ApplicationBarItem);
                                }
                                start++;
                            }
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    {  
                        if (e.NewItems != null)
                        {
                            foreach (var item in e.NewItems)
                            {
                                AppBarMenuItem menuItem = item as AppBarMenuItem;
                                if (menuItem != null && !string.IsNullOrEmpty(menuItem.Text))
                                    ApplicationBar.MenuItems.Remove(menuItem.ApplicationBarItem);
                            }
                        }
                    }
                    break;

                default:
                    {
                        ApplicationBar.MenuItems.Clear();
                        if (Menus != null)
                        {
                            foreach (AppBarMenuItem item in Menus)
                            {
                                if (!string.IsNullOrEmpty(item.Text))
                                {
                                    ApplicationBar.MenuItems.Add(item.ApplicationBarItem);
                                }
                            }
                        }
                    }
                    break;
            }
        }
        #endregion

        #region - MiniSize -
        public static readonly DependencyProperty MiniSizeProperty =
        DependencyProperty.Register("MiniSize",
        typeof(double),
        typeof(AppBar),
        new PropertyMetadata(0.0, new PropertyChangedCallback(AppBar.OnMiniSizePropertyChanged)));

        public double MiniSize
        {
            get
            {
                return (double)base.GetValue(MiniSizeProperty);
            }
            set
            {
                base.SetValue(MiniSizeProperty, value);
            }
        }

        private static void OnMiniSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }
        #endregion

        #region - DefaultSize -
        public static readonly DependencyProperty DefaultSizeProperty =
        DependencyProperty.Register("DefaultSize",
        typeof(double),
        typeof(AppBar),
        new PropertyMetadata(0.0, new PropertyChangedCallback(AppBar.OnDefaultSizePropertyChanged)));

        public double DefaultSize
        {
            get
            {
                return (double)base.GetValue(DefaultSizeProperty);
            }
            set
            {
                base.SetValue(DefaultSizeProperty, value);
            }
        }

        private static void OnDefaultSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }
        #endregion

        #region - Mode -
        public static readonly DependencyProperty ModeProperty =
        DependencyProperty.Register("Mode",
        typeof(ApplicationBarMode),
        typeof(AppBar),
        new PropertyMetadata(ApplicationBarMode.Default, new PropertyChangedCallback(AppBar.OnModePropertyChanged)));

        public ApplicationBarMode Mode
        {
            get
            {
                return (ApplicationBarMode)base.GetValue(ModeProperty);
            }
            set
            {
                base.SetValue(ModeProperty, value);
            }
        }

        private static void OnModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.Mode = (ApplicationBarMode)e.NewValue;
        }
        #endregion

        #region - Opacity -
        public static readonly DependencyProperty OpacityProperty =
        DependencyProperty.Register("Opacity",
        typeof(double),
        typeof(AppBar),
        new PropertyMetadata(1.0, new PropertyChangedCallback(AppBar.OnOpacityPropertyChanged)));

        public double Opacity
        {
            get
            {
                return (double)base.GetValue(OpacityProperty);
            }
            set
            {
                base.SetValue(OpacityProperty, value);
            }
        }

        private static void OnOpacityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as AppBar).ApplicationBar.Opacity = (double)e.NewValue;
        }
        #endregion

        #region - AutoUse -
        /// <summary>
        /// 自动应用到页面
        /// </summary>
        public static readonly DependencyProperty AutoUseProperty =
        DependencyProperty.Register("AutoUse",
        typeof(bool),
        typeof(AppBar),
        new PropertyMetadata(false, new PropertyChangedCallback(AppBar.OnAutoUsePropertyChanged)));

        public bool AutoUse
        {
            get
            {
                return (bool)base.GetValue(AutoUseProperty);
            }
            set
            {
                base.SetValue(AutoUseProperty, value);
            }
        }

        private static void OnAutoUsePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var parentPage = (d as AppBar).ParentPage;
            if (parentPage == null)
                return;

            if ((bool)e.NewValue)
            {
                parentPage.ApplicationBar = (d as AppBar).ApplicationBar;
            }
            else if (parentPage.ApplicationBar == (d as AppBar).ApplicationBar)
            {
                parentPage.ApplicationBar = null;
            }
        }
        #endregion

        public event EventHandler<ApplicationBarStateChangedEventArgs> StateChanged;

        void appBar_StateChanged(object sender, ApplicationBarStateChangedEventArgs e)
        {
            if (this.StateChanged != null)
                StateChanged(sender, e);
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            return base.MeasureOverride(availableSize);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            var p = GetParentPhonePage(this);
            if (p != null && AutoUse)
            {
                ParentPage = p;
                if (AutoUse)
                {
                    ParentPage.ApplicationBar = this.ApplicationBar;
                }
            }
            return base.ArrangeOverride(finalSize);
        }

        public static PhoneApplicationPage GetParentPhonePage( DependencyObject start)
        {
            if (start == null)
                return null;

            DependencyObject parent = start;
            DependencyObject current;

            do
            {
                current = parent;
                parent = VisualTreeHelper.GetParent(parent);
                if (parent is PhoneApplicationPage)
                    return parent as PhoneApplicationPage;

            } while (parent != null);

            if (current is PhoneApplicationPage)
                return current as PhoneApplicationPage;

            return null;
        }
    }
}
